import uuid
from datetime import timedelta
from django.utils import timezone
from django.db import transaction
import json
from django.http import JsonResponse
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from rest_framework import status, generics, viewsets, permissions
from rest_framework.decorators import action
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework_simplejwt.tokens import RefreshToken

from apps.user.models import UserProfile, SessionLog, Family, InvitationCode, FamilyMember
from apps.user.permissions import HasNoFamily, IsFamilyMember, IsFamilyAdmin
from apps.user.serializers import InvitationCodeSerializer, FamilySerializer, JoinFamilySerializer, FamilyMemberSerializer


class FamilyViewSet(viewsets.ModelViewSet):
    """
    家庭系统集成视图集
    POST    /family/               -> 创建家庭
    POST    /family/generate_invite/ -> 生成邀请码
    POST    /family/join/          -> 加入家庭
    GET     /family/members/       -> 查看成员
    DELETE  /family/leave/         -> 退出家庭
    """
    queryset = Family.objects.all()
    serializer_class = FamilySerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):  # 覆盖默认查询集
        """动态过滤用户所属家庭"""
        if self.action == 'list':
            return Family.objects.filter(members__user=self.request.user)
        return super().get_queryset()

    def get_permissions(self):
        """动态权限控制规则：
        - 创建家庭：需要用户未加入任何家庭
        - 生成邀请码：需要家庭管理员权限
        - 加入家庭：需要用户未加入任何家庭
        - 成员操作：需要属于当前家庭
        - 其他操作：默认需要认证
        """
        if self.action == 'create':
            return [
                IsAuthenticated(),  # 必须登录
                HasNoFamily()  # 不能已有家庭
            ]
        elif self.action == 'generate_invite':
            return [
                IsAuthenticated()
            ]
        elif self.action == 'join':
            return [
                IsAuthenticated(),
                HasNoFamily()  # 加入前需无家庭
            ]
        elif self.action in ['members', 'leave']:
            return [
                IsAuthenticated(),
                IsFamilyMember()  # 必须属于家庭
            ]
        else:
            # 默认权限（如列表查看、更新等操作）
            return [IsAuthenticated()]

    # 创建家庭（自动关联管理员）
    @action(detail=True, methods=['post'], url_path='create')
    def perform_create(self, serializer):
        with transaction.atomic():
            family = serializer.save(manager=self.request.user.userprofile)
            FamilyMember.objects.create(
                user=self.request.user,
                family=family,
                role='admin'
            )

    # 生成邀请码
    @action(detail=False, methods=['post'])
    def generate_invite(self, request):
        family = request.user.familymember.family
        code = InvitationCode.objects.create(
            family=family,
            created_by=request.user,
            expires_at=timezone.now() + timedelta(hours=24)
        )
        return Response({
            "code": str(code.code),
            "expires_at": code.expires_at
        }, status=status.HTTP_201_CREATED)

    # 加入家庭
    @action(detail=False, methods=['post'])
    def join(self, request):
        serializer = JoinFamilySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        with transaction.atomic():
            code = uuid.UUID(serializer.validated_data['code'])
            invitation = get_object_or_404(
                InvitationCode,
                code=code,
                used=False,
                expires_at__gt=timezone.now()
            )

            FamilyMember.objects.create(
                user=request.user,
                family=invitation.family,
                role='member'
            )
            invitation.used = True
            invitation.save()

        return Response({"ok": True, "status": "加入成功"}, status=status.HTTP_200_OK)

    # 查看家庭成员
    @action(detail=False, methods=['get'], url_path='members')
    def members(self, request):
        family = request.user.familymember.family
        members = FamilyMember.objects.filter(family=family)
        serializer = FamilyMemberSerializer(members, many=True)
        return Response(serializer.data)

    # 退出家庭
    @action(detail=False, methods=['delete'])
    def leave(self, request):
        """退出家庭逻辑"""
        try:
            # 获取当前用户家庭关系
            user_membership = FamilyMember.objects.get(user=request.user)
            family = user_membership.family

            # 权限转移逻辑
            if user_membership.role == 'admin':
                # 查找其他管理员或成员
                new_admin = family.members.exclude(user=request.user).first()

                if new_admin:
                    # 转移管理员权限
                    family.manager = new_admin.user.userprofile
                    family.save()
                    new_admin.role = 'admin'
                    new_admin.save()
                else:
                    # 没有其他成员则删除家庭
                    family.delete()

            # 删除成员关系
            user_membership.delete()

            return Response({'ok': True, 'message': "已退出家庭"}, status=status.HTTP_200_OK)
        except FamilyMember.DoesNotExist:
            return Response(
                {"detail": "用户未加入任何家庭"},
                status=status.HTTP_400_BAD_REQUEST
            )


class AuthViewSet(viewsets.ViewSet):
    """
    POST    /auth/register/    -> 用户注册
    POST    /auth/login/       -> 用户登录
    POST    /auth/logout/      -> 用户注销
    POST    /auth/refresh/     -> Token刷新
    GET     /auth/profile/     -> 用户资料
    """

    def get_permissions(self):
        if self.action in ['register', 'login', 'logout']:
            return [AllowAny()]
        else:
            return [IsAuthenticated()]

    @action(detail=False, methods=['post'])
    def register(self, request):
        """
        用户注册
        POST /auth/register/
        """
        try:
            data = json.loads(request.body)
            required_fields = ['username', 'password', 'nickname']

            if not all(data.get(f) for f in required_fields):
                return JsonResponse({
                    "ok": False,
                    "error": {"code": "MISSING_FIELDS", "message": "必填字段: " + ", ".join(required_fields)}
                }, status=422)

            username = data['username']
            if User.objects.filter(username=username).exists():
                return JsonResponse({
                    "ok": False,
                    "error": {"code": "USER_EXISTS", "message": "用户名已存在"}
                }, status=409)

            with transaction.atomic():
                user = User.objects.create_user(username=username, password=data['password'])
                UserProfile.objects.create(
                    user=user,
                    nickname=data['nickname'],
                    avatar_url=data.get('avatar_url', ''),
                    timezone=data.get('timezone', 'UTC')
                )
                refresh = RefreshToken.for_user(user)

                return JsonResponse({
                    "ok": True,
                    "data": {
                        "user_id": user.id,
                        "tokens": {
                            "access": str(refresh.access_token),
                            "refresh": str(refresh)
                        }
                    }
                }, status=201)

        except json.JSONDecodeError:
            return JsonResponse({
                "ok": False,
                "error": {"code": "INVALID_JSON", "message": "无效的JSON格式"}
            }, status=400)
        except Exception as e:
            return JsonResponse({
                "ok": False,
                "error": {"code": "SERVER_ERROR", "message": "服务器内部错误"}
            }, status=500)

    @action(detail=False, methods=['post'])
    def login(self, request):
        """用户登录接口"""
        try:
            # 添加请求体格式验证
            try:
                data = json.loads(request.body)
            except json.JSONDecodeError:
                return Response({
                    "ok": False,
                    "error": {"code": "INVALID_JSON", "message": "无效的JSON格式"}
                }, status=400)

            # 增强字段验证
            username = data.get('username')
            password = data.get('password')
            if not username or not password:
                return Response({
                    "ok": False,
                    "error": {"code": "MISSING_FIELDS", "message": "必须提供用户名和密码"}
                }, status=400)

            user = authenticate(username=username, password=password)
            if not user:
                return Response({
                    "ok": False,
                    "error": {"code": "INVALID_CREDENTIALS", "message": "用户名或密码错误"}
                }, status=401)

            # 确保用户资料存在
            session = SessionLog.objects.create(
                user=user,  # 确保关联的是UserProfile实例
                ip=request.META.get('REMOTE_ADDR'),
                user_agent=request.META.get('HTTP_USER_AGENT', '')
            )

            # 生成Token
            refresh = RefreshToken.for_user(user)
            refresh['session_id'] = session.id
            return Response({
                "ok": True,
                "data": {
                    "access": str(refresh.access_token),
                    "refresh": str(refresh)
                }
            }, status=200)

        except Exception as e:
            # 添加详细错误日志
            print(f"登录异常: {str(e)}")  # 生产环境应使用logger
            return Response({
                "ok": False,
                "error": {"code": "SERVER_ERROR", "message": "登录服务暂时不可用"}
            }, status=500)

    @action(detail=False, methods=['post'], permission_classes=[IsAuthenticated])
    def logout(self, request):
        """
        用户注销
        POST /auth/logout/
        """
        try:
            refresh_token = request.data.get("refresh")
            if not refresh_token:
                return Response({
                    "ok": False,
                    "error": {"code": "MISSING_TOKEN", "message": "必须提供 refresh token"}
                }, status=400)

            token = RefreshToken(refresh_token)
            token.blacklist()

            # 更新会话日志
            if session_id := token.get('session_id'):
                SessionLog.objects.filter(id=session_id).update(logout_at=timezone.now())

            return Response({"ok": True, "data": {"message": "成功注销"}})

        except TokenError:
            return Response({
                "ok": False,
                "error": {"code": "INVALID_TOKEN", "message": "无效的Token"}
            }, status=401)

    @action(detail=False, methods=['post'])
    def refresh(self, request):
        """
        Token刷新
        POST /auth/refresh/
        """
        try:
            refresh = RefreshToken(request.data.get('refresh'))
            access = str(refresh.access_token)

            return JsonResponse({
                "ok": True,
                "data": {
                    "access": access,
                    "refresh": str(refresh)  # 如果配置允许刷新
                }
            })

        except TokenError as e:
            return JsonResponse({
                "ok": False,
                "error": {"code": "INVALID_TOKEN", "message": "无效的刷新Token"}
            }, status=401)

    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def profile(self, request):
        """
        获取用户资料
        GET /auth/profile/
        """
        profile = request.user.userprofile
        return Response({
            "username": request.user.username,
            "avatar_url": profile.avatar_url,
            "nickname": profile.nickname,
            "timezone": profile.timezone
        })
